#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<assert.h>
#include<stdlib.h>

#define BUFSIZE 1024

struct myfile_{
  int fd;
  char buffer[BUFSIZE];
  int end;
};

typedef struct myfile_ myfile;

myfile* fopen_(const char*filename,const char*mode)
{
  assert(filename);
  assert(mode);
  myfile*fp=malloc(sizeof(myfile));
  memset(fp,0,sizeof(myfile));
  int fd=-1;
  if(strcmp(mode,"r")==0)
  {
    fd=open(filename,O_RDONLY); 
  }else if(strcmp(mode,"w")==0)
  {
    fd=open(filename,O_CREAT|O_TRUNC|O_WRONLY);
  }else if(strcmp(mode,"a")==0)
  {
    fd=open(filename,O_CREAT|O_APPEND|O_WRONLY);
  }else
  {
    perror("unknown mode\n");
    exit(2);
  }
  fp->fd=fd;
  return fp;
}


void fflush_(myfile* fp);
void fputs_(const char*message,myfile*fp)
{
  assert(message);
  assert(fp);

  if(fp->end+strlen(message)>BUFSIZE)
  {
    fflush_(fp);
  }
  
  strcpy(fp->buffer+fp->end,message);
  fp->end+=strlen(message);
  
  if(fp->fd==1)
  {
    if(fp->buffer[fp->end-1]=='\n')
    {
      fflush_(fp);
    }
  }
}

void fflush_(myfile* fp)
{
  assert(fp);
  if(fp->end==0)return;
  write(fp->fd,fp->buffer,fp->end);
  fp->end=0;
  syncfs(fp->fd);
}

void fclose_(myfile* fp)
{
  assert(fp);
  fflush_(fp);
  close(fp->fd);
  free(fp);
}




int main(int argc,const char*argv[])
{
  myfile*fp=fopen_("log.txt","w");
  if(fp==NULL)
  {
    perror("fopen_ fail:");
    exit(1);
  }

  myfile*stdout_;
  stdout_->fd=1;

  fputs_("hello stdout_\n",stdout_); 
  
  fputs_("hello log.txt\n",fp); 
  fputs_("hello log.txt\n",fp); 
  fputs_("hello log.txt\n",fp); 

 // fflush_(fp);
  fork();
  fclose_(fp);
  return 0;
}
